// Copyright 2014 Flávio Ribeiro <flavio@bem.tv>.
// All rights reserved.
// Use of this source code is governed by Apache
// license that can be found in the LICENSE file.

var Settings = require('./settings')
var ResourceRequester = require('./resource_requester')
var UploadHandler = require('./upload_handler')
var PlaybackInfo = require('./playback_info')
var AdaptiveStreaming = require('./adaptive_streaming')
var Storage = require('./storage')
var FlashUploader = require('./flash_uploader')
var log = require('./log').getInstance()
var JST = require('./jst')
var Browser = require('browser')
var Styler = require('./styler')
var HLS = require('hls')
var version = require('../package.json').version
var _ = require('underscore')

// require module để thiết lập phím set p2phls true or false
var Mousetrap = require('mousetrap')

class P2PHLS extends HLS {
  get name() { return 'p2phls' }
  get tagName() { return 'object' }
  get template() { return JST.p2phls }
  get attributes() {
    return {
      'data-p2phls': '',
      'type': 'application/x-shockwave-flash'
    }
  }

  get info() {
    //return "this";
    return this.playbackInfo.infoChunks
  }

  constructor(options) {
    Settings = _.extend(Settings, options.p2phls) 
    //options.swfPath = "http://tvstatic.vcmedia.vn/p2ptv/dist/assets/P2PHLSPlayer.swf"
    this.resourceRequester = new ResourceRequester({swarm: btoa(options.src.split("?")[0]), tracker: options.tracker})
    this.uploadHandler = UploadHandler.getInstance()
    this.playbackInfo = PlaybackInfo.getInstance()
    this.storage = Storage.getInstance()
    super(options) // gọi hàm constructor của lớp cha
    this.init(options)
    Mousetrap.bind(['command+shift+k', 'ctrl+shift+k'], () => this.setURLStream())
  }

  init(options) {
    if (options.type == 'vod') {
      Settings.P2PRequest = false
    } else if (options.type == 'live') {
      Mousetrap.bind(['command+shift+h', 'ctrl+shift+h'], () => this.setP2PRequest())
    }
  }

  setP2PRequest() {
    Settings.P2PRequest = !(Settings.P2PRequest);
    log.info("P2PRequest is " + Settings.P2PRequest)

  }

  addListeners() {
    Soha.Mediator.on(this.uniqueId + ':flashready', () => this.bootstrap())
    Soha.Mediator.on(this.uniqueId + ':timeupdate', () => this.updateTime())
    Soha.Mediator.on(this.uniqueId + ':playbackstate', (state) => this.setPlaybackState(state))
    Soha.Mediator.on(this.uniqueId + ':highdefinition', (isHD) => this.updateHighDefinition(isHD))
    Soha.Mediator.on(this.uniqueId + ':playbackerror', () => this.flashPlaybackError())
    Soha.Mediator.on(this.uniqueId + ':requestresource', (url) => this.requestResource(url))
    Soha.Mediator.on(this.uniqueId + ':decodeerror', () => this.onDecodeError())
    Soha.Mediator.on(this.uniqueId + ':decodesuccess', () => this.onDecodeSuccess())
    //Soha.Mediator.on(this.uniqueId + ':lostconnect', () => this.onLostConnect())
    //Soha.Mediator.on(this.uniqueId + ':crossdomainerror', () => this.onCrossDomain())
    //Soha.Mediator.on(this.uniqueId + ':lowbandwidth', () => this.onLowBandwidth())
  }

  stopListening() {
    Soha.Mediator.off(this.uniqueId + ':flashready')
    Soha.Mediator.off(this.uniqueId + ':timeupdate')
    Soha.Mediator.off(this.uniqueId + ':playbackstate')
    Soha.Mediator.off(this.uniqueId + ':highdefinition')
    Soha.Mediator.off(this.uniqueId + ':playbackerror')
    Soha.Mediator.off(this.uniqueId + ':requestresource')
    Soha.Mediator.off(this.uniqueId + ':decodeerror')
    Soha.Mediator.off(this.uniqueId + ':decodesuccess')
  }

  bootstrap() {
    this.playbackInfo.setMain(this)
    this.adaptiveStreaming = new AdaptiveStreaming(this)
    this.el.playerSetminBufferLength(6)
    this.el.playerSetlowBufferLength(Settings.lowBufferLength)
    super()
  }

  setPlaybackState(state) {
    if (state === 'PLAYING' && this.resourceRequester.isInitialBuffer) {
      this.resourceRequester.isInitialBuffer = false
    }
     log.warn(state)
    if (state === 'PLAYING' || state === 'IDLE') {
       this.$el.parent().find('#soha-message').hide()
    }
    super(state)
  }

  setURLStream() {
    if (Settings.BemTVURLStream == true) {
      log.info('JSURLStream is false')
      Settings.BemTVURLStream = false;
      this.el.playerSetJSURLStream(false);
    } else {
      log.info('JSURLStream is true')
      Settings.BemTVURLStream = true;
      this.el.playerSetJSURLStream(true);
    }
  }

  onDecodeError() {
    log.warn("Error, decode error")
    this.resourceRequester.decodingError = true
    this.resourceRequester.requestResource(this.currentUrl, 0, (chunk, method) => this.resourceLoaded(chunk, method), () => this.requestError())
  }

  onDecodeSuccess() {
    if (this.currentUrl) {
      this.resourceRequester.decodingError = false
      this.storage.setItem(this.currentUrl, this.currentChunk)
      this.currentUrl = null
      this.currentChunk = null
    }
  }

  onLostConnect() {
     this.$el.parent().find('.poster-icon.play').hide()
     this.sohaMessage('Mất kết nối internet.<br>Bạn vui lòng kiểm tra lại !!!')
  }

  onLowBandwidth() {
    log.warn("Low Bandwidth")
    //this.el.globoPlayerStop()
    this.$el.parent().find('.poster-icon.play').hide()
    this.$el.parent().find('.spinner-three-bounce').hide()
    this.$el.parent().find('.player-poster').bind('click',function(){ 
      $(this).parent().find('#soha-message').hide()
      $(this).parent().find('.player-poster').unbind('click')
    })
    /*this.$el.parent().parent().find('.media-control-button.media-control-icon.playing').bind('click',function() {
      this.el.globoPlayerStop()
      this.$el.parent().parent().find('.media-control-button.media-control-icon.playing').unbind('click')
    }.bind(this))*/
    this.sohaMessage('Kết nối với server hiện rất chậm !!!')
  }

  onCrossDomain() {
    //log.warn("Cross Domain")
    this.$el.parent().find('.poster-icon.play').hide()
    this.el.globoPlayerStop()
    this.sohaMessage('Bạn vui lòng truy cập vào vtv.vn<br>để theo dõi với chất lượng tốt nhất !!!')
  }

  sohaMessage(message) {
    if (this.$el.parent().find('.sohamessage').length != 0) {
      this.$el.parent().find('.sohamessage').html(message)
      this.$el.parent().find('#soha-message').show()
    } else {
      this.$el.parent().append(Settings.sohamessage({message: message}))
    }
  }

  requestResource(url) {
    if (this.currentUrl) {
      log.warn("still processing the other chunk, wait :)")
    } else {
      this.currentUrl = url
      if (this.storage.contain(this.currentUrl)) {
        this.resourceLoaded(this.storage.getItem(this.currentUrl), "storage")
      } else {
        this.resourceRequester.requestResource(url, this.el.globoGetbufferLength(), (chunk, method) => this.resourceLoaded(chunk, method), () => this.requestError())
      }
    }
  }

  resourceLoaded(chunk, method) {
    log.warn("resourceLoaded")
    if (this.currentUrl) {
      this.currentChunk = chunk
      this.flashUploader = new FlashUploader()
      var sendPartCallback = function(part) { 
        //log.warn("sendPartCallback")
        this.el.resourceLoaded(part) 
      }.bind(this)
      var finishSendingCallback = function() { this.el.startDecoding() }.bind(this)
      this.flashUploader.send(sendPartCallback, chunk, finishSendingCallback)
      this.playbackInfo.updateChunkStats(method)
    }
  }

  requestError() {
    //this.el.playerResourceLoadError
    
    this.resourceLoaded("","cdn")
  }

  seek(time) {
    this.resourceRequester.onDVR = time !== -1? true: false
    //console.log("onDVR", this.resourceRequester.onDVR)
    super(time)
  }

  render() {
    this.$el.html(this.template({cid: this.cid, swfPath: this.swfPath, playbackId: this.uniqueId}))
    if(Browser.isFirefox) {
      this.setupFirefox()
    }
    this.el.id = this.cid
    var style = Styler.getStyleFor(this.name)
    this.$el.append(style)
    return this
  }

}

P2PHLS.canPlay = function(resource) {
  return !!(window.webkitRTCPeerConnection || window.mozRTCPeerConnection) && !!resource.match(/^http(.*).m3u8/)
}

P2PHLS.version = version

module.exports = window.P2PHLS = P2PHLS;
